﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Assembler;
using System.IO;
namespace AssemblerGUI
{
    public partial class MainForm : Form
    {
        private StreamReader reader;
        private Assembler.Assembler assembler;
        public MainForm()
        {
            InitializeComponent();
        }

        private void btnLoadFile_Click(object sender, EventArgs e)
        {
            string fileName;
            if (dlgOpenFile.ShowDialog() == DialogResult.OK)
            {
                fileName = dlgOpenFile.FileName;
                lblFileName.Text = fileName;
                lblFileName.Visible = true;

                reader = new StreamReader(fileName);
                assembler = new Assembler.Assembler(reader);

                loadInstructionText();
                
            }

        }

        /**
         * Loads the symbol table from Assembler
         **/
        private void loadSymbolTableText()
        {
            string symbolTableStr = "";

            //6 space separator between label / left edge / addr
            string margin = "      ";

            Dictionary<string, int> symTable = assembler.symTable;
            foreach (KeyValuePair<string, int> lbl in symTable)
            {
                symbolTableStr += margin;
                symbolTableStr += lbl.Key;
                symbolTableStr += margin;
                symbolTableStr += lbl.Value.ToString("x");
                symbolTableStr += "\n";
            }

            txtSymbolTable.Text = symbolTableStr;
        }
        /**
         * Loads the text for the main text box from assembly instructions
         **/
        private void loadInstructionText()
        {
            string instructionText = "";
            string header = "";

            int maxCommentSize = 0;
            int maxLineLength = 15;
            List<Instruction> instructions = assembler.instructions;
            foreach (Instruction i in instructions)
            {
                instructionText += i.label;
                if (i.label != Instruction.EMPTY_STRING)
                {
                    instructionText += ",";
                }
                else
                {
                    instructionText += " ";
                }
                instructionText += " ";
                instructionText += i.opcode + " ";
                instructionText += i.refAddress + " ";
                if (i.indirect)
                {
                    instructionText += "I ";
                }
                instructionText += i.comment + "\n";
                if (i.comment.Length > maxCommentSize)
                {
                    maxCommentSize = i.comment.Length;
                }
            }
            maxLineLength += maxCommentSize + 1;

            header = getHeader(maxLineLength);

            txtAssembly.Text = instructionText;
            txtHeader.Text = header;
        }

        /**
         * generates the header for the text fields in main form.
         * param maxLineLength: maximum number of columns in a line
         * which determines how long the header is.
         **/
        private string getHeader(int maxLineLength)
        {
            string firstLine = "";
            string dashes = "";
            string result = "";
            bool skipNextSpace = false;

            //setup column labels
            for (int pos = 1; pos < maxLineLength + 1; pos++)
            {
                if (pos % 5 == 0 || pos == 1)
                {
                    firstLine += pos;
                    //if pos > 9 we take up two columns for label
                    if (pos > 9)
                    {
                        skipNextSpace = true;
                    }
                }
                else
                {
                    if (!skipNextSpace)
                    {
                        firstLine += " ";
                    }
                    skipNextSpace = false;
                }
            }
            firstLine += "\n";

            //create dashes under column labels
            for (int pos = 0; pos < maxLineLength; pos++)
            {
                dashes += "-";
            }
            dashes += "\n";
            result = String.Concat(firstLine, dashes);
   
            return result;
        }

        private void btnAssemble_Click(object sender, EventArgs e)
        {
            assembler.assemble();
            loadSymbolTableText();
        }

        private void panelInstructions_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}
